home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 344_01 / cflow.c < prev    next >
C/C++ Source or Header  |  1990-12-03  |  15KB  |  516 lines

  1. /*
  2.         HEADER:         CUG236;
  3.         TITLE:          Function Abstractor;
  4.         DATE:           04/19/1987;
  5.         DESCRIPTION:    "Abstracts C function calls and declarations from a C
  6.                         source and produces a listing of the program's calling
  7.                         hierarchy."
  8.         VERSION:        3.0;
  9.         KEYWORDS:       Flow Analysis, Flow Analyzer;
  10.         FILENAME:       CFLOW.C;
  11.         SEE-ALSO:       CFLOW.DOC;
  12.         COMPILERS:      vanilla;
  13.         AUTHORS:        W. C. Colley III, Mark Ellington;
  14. */
  15.  
  16. /*
  17. **   CFLOW.C : find module call structure of c program
  18. **   refer to cflow.doc for how to use
  19. **                                      Mark Ellington
  20. **                                      05-27-84
  21. **
  22. **   Ported to portable C.  Required the following changes:
  23. **
  24. **      1)  Stripped BDS C hooks.
  25. **      2)  Stripped C/80 hooks.
  26. **      3)  Allowed for presence/absence of header files "ctype.h"
  27. **              and "string.h".
  28. **      4)  Allowed for possible pre-definition of constants TRUE,
  29. **              FALSE, and EOF.
  30. **      5)  Made variable fptr type FILE * instead of int.
  31. **      6)  Added a #define for the max line length.
  32. **      7)  Made preprocessor directive rejection logic smarter.
  33. **      8)  Removed name conflict between our fgets() and the std
  34. **          library fgets() by changing ours to get_source_line().
  35. **                                      William C. Colley, III
  36. **                                      04-19-87
  37. */
  38.  
  39. #include <stdio.h>
  40.  
  41. /*
  42.  * Portability Note:  The AZTEC C compilers handle the binary/text file
  43.  * dichotomy differently from most other compilers.  Uncomment the following
  44.  * pair of #defines if you are running AZTEC C:
  45.  */
  46.  
  47. /*
  48. #define getc(f)         agetc(f)
  49. #define putc(c,f)       aputc(c,f)
  50. */
  51.  
  52. /*  Portability Note:  If you do not have a header file "ctype.h",
  53.     uncomment the following #define so that the program will look for
  54.     library support.                                                    */
  55.  
  56. /* #define      NO_CTYPE_H                                              */
  57.  
  58. #ifdef  NO_CTYPE_H
  59. extern int isalnum();
  60. #else
  61. #include <ctype.h>
  62. #endif
  63.  
  64. /*  Portability Note:  If you do not have a header file "string.h",
  65.     uncomment the following #define so that the program will look for
  66.     library support.                                                    */
  67.  
  68. /* #define      NO_STRING_H                                             */
  69.  
  70. #ifdef  NO_STRING_H
  71. extern int strcmp();
  72. #else
  73. #include <string.h>
  74. #include <dos.h>
  75. #include <dir.h>
  76. #endif
  77.  
  78. /*  Portability Note:  A few compilers don't know the additional type
  79.     void.  If yours is one of these, uncomment the following #define.   */
  80.  
  81. /* #define      void            int                                     */
  82.  
  83. #ifndef TRUE
  84. #define TRUE    1
  85. #endif
  86.  
  87. #ifndef FALSE
  88. #define FALSE   0
  89. #endif
  90.  
  91. #ifndef EOF
  92. #define EOF     -1
  93. #endif
  94.  
  95. #define LINE_LENGTH     256     /* Max line length program can handle.  */
  96. #define PAGE_LENGTH     55      /* lines per page                       */
  97.  
  98. FILE *fptr;                     /* input file pointer                   */
  99. int level;                      /* keep track of level of open "{"s     */
  100. char name[LINE_LENGTH];         /* module name buffer                   */
  101. char ins[LINE_LENGTH];          /* source input line buffer             */
  102. int curchar;                    /* current character in input line
  103.                                         buffer array subscript          */
  104. unsigned short int linenum;     /* current line number                  */
  105. unsigned short int linecnt;     /* hidden line number                   */
  106. int function = FALSE;           /* flag for level zero only             */
  107. char filename[128];             /* holder for filename                  */
  108. short int lpp;                  /* holder for lines per page            */
  109. struct date today;              /* structure for todays date            */
  110. struct time now;                /* structure for current time           */
  111. short int pageno;               /* holder for page number               */
  112. struct ffblk ffblk;             /* holder for file structure            */
  113.  
  114. /*  Fixed bug that makes _ characters lop off the beginning of function
  115.     names.  WCC3.                                                       */
  116.  
  117. /**********************************************************************/
  118.  
  119. int main(argc,argv)
  120. int argc;
  121. char *argv[];
  122. {
  123.    void modules(), prt_hdr();
  124.    int i, done, filenum;
  125.    unsigned long int ttllines;
  126.  
  127.    if (argc < 2) {
  128.       fprintf(stderr,"\nUsage: cflow infilename.ext [-f] ");
  129.       return TRUE;
  130.    }
  131.  
  132.    if (done = findfirst(argv[1], &ffblk, 0)) {
  133.       fprintf(stderr,"\nCan't open %s\n",argv[1]);
  134.       return TRUE;
  135.    }
  136.  
  137.    if (argc > 2)
  138.       if (argv[2][0] == '-' && (argv[2][1] == 'f' || argv[2][1] == 'F'))
  139.          function = TRUE;
  140.       else {
  141.          fprintf(stderr,"Second parameter is either '-f' or '-F'.");
  142.          return TRUE;
  143.       }
  144.  
  145.    getdate(&today);
  146.    gettime(&now);
  147.    filenum = 0;
  148.    ttllines = 0;
  149.  
  150.    while (!done) {
  151.       for (i = 0; ffblk.ff_name[i]; i++)
  152.          filename[i] = toupper(ffblk.ff_name[i]);
  153.       filename[i] = NULL;
  154.  
  155.       if (!(fptr = fopen(filename,"r")))
  156.          break;
  157.  
  158.       if (!function) {
  159.          pageno = 0;
  160.          prt_hdr();
  161.       } 
  162.       else
  163.          fprintf(stderr,"File: %s\n", filename);
  164.  
  165.       if (filenum++ > 1)
  166.          ttllines += linenum;
  167.       linenum = linecnt = 0;
  168.  
  169.       modules();
  170.  
  171.       fclose(fptr);
  172.  
  173.       done = findnext(&ffblk);
  174.    }
  175.    if (filenum > 1)
  176.       fprintf(stderr, "Processed %d files, %u lines\n", filenum, ttllines);
  177.  
  178.    return FALSE;
  179.  
  180. }
  181.  
  182. /**********************************************************************/
  183.  
  184. void modules()          /* find function declarations and calls         */
  185. {
  186.    char c;
  187.    int i, dquote, defcont;
  188.    int incom;      /* comment flag                                 */
  189.    int decl;       /* module declaration line flag                 */
  190.    int quoted;     /* within " quotes "                            */
  191.    int header;     /* within function header (before 1st '{')      */
  192.    int lookbak();
  193.    void comout(), modname(), prt_hdr();
  194.  
  195.    incom = quoted = header = defcont = dquote = FALSE;
  196.    level = 0;
  197.  
  198.    while (fgets(ins, LINE_LENGTH, fptr)) { /* read a line of source */
  199.       linenum++;
  200.       decl = FALSE;           /* assume nothing               */
  201.       curchar = 0;
  202.  
  203.       while (ins[curchar]) {  /* read for significant characters */
  204.  
  205. comment:
  206.          if (ins[curchar] == '/' && (!quoted)) /* comments ? */
  207.             if (incom) {
  208.                if (curchar && (ins[curchar-1] == '*')) {
  209.                   incom = FALSE;
  210.                   curchar++;
  211.                }
  212.             } 
  213.             else
  214.                if (ins[curchar+1] == '*') {
  215.                   incom = TRUE;
  216.                   curchar += 2;
  217.                   if (ins[curchar] == '/')
  218.                      curchar++;
  219.                }
  220.  
  221.          if (!incom) {
  222.             if (defcont) { /* delete preprocessor continued lines */
  223. def_cont:
  224.                defcont = TRUE;
  225.                for (i = curchar; ins[i]; i++)
  226.                   switch (ins[i]) {
  227.  
  228.                   case '\\':
  229.                      i++;
  230.                      break;
  231.  
  232.                   case '\'':
  233.                      if (!dquote) {
  234.                         if (ins[++i] == '\\')
  235.                            i++;
  236.                         i++;
  237.                      }
  238.                      break;
  239.  
  240.                   case '"':
  241.                      dquote = !dquote;
  242.                      break;
  243.  
  244.                   case '/':
  245.                      if (!dquote)
  246.                         if (ins[i+1] == '*') {
  247.                            curchar = i;
  248.                            goto comment;
  249.                         }
  250.                      break;
  251.  
  252.                   } /* end switch */
  253.  
  254.                if (ins[i-2] != '\\' || ins[i-1] != '\n